package com.self.ry.utils;

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import net.minidev.json.JSONObject;
import org.apache.commons.codec.binary.Base64;

import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Copyright: Copyright (c) 2018
 *
 * @Description: JSON Web Token(JWT) 辅助类
 * 1. 作成token
 * 2. 校验token
 * @version: v1.0.0
 * @author: 汝毅
 * @date: 2018/11/7 13:44
 * <p>
 * Modification History:
 * Date         Author          Version            Description
 * ---------------------------------------------------------*
 * 2018/11/7     汝毅           v1.0.0               修改原因
 */
public final class JwtUtil {
    /**
     * 至少256bit位，但是不能为null
     * 也可以是48个字节，也可以是64个字节
     * 要根据JWSHeader中指定的算法位数（JWSAlgorithm.HS256）来设定长度
     * <p>
     * 可以随便指定一组字符串
     */
    private final static byte[] SECRET = Base64.decodeBase64("121424324324324");

    // header 部分主要包括两部分，一个是 Token 的类型，另一个是使用的算法
    private static final JWSHeader header = new JWSHeader(
            JWSAlgorithm.HS256,
            JOSEObjectType.JWT,
            null, null, null, null, null, null, null,
            null, null, null, null);

    /**
     * 根据给定内容生成token
     *
     * @param payload 内容载体
     * @return
     */
    public static String createSecretToken(Map<String, Object> payload) {
        String token = "";
        try {
            JWSSigner macSigner = new MACSigner(SECRET);
            // Create an HMAC-protected JWS object with some payload
            JWSObject jwsObject = new JWSObject(header, new Payload(new JSONObject(payload)));
            // Apply the HMAC to the JWS object
            jwsObject.sign(macSigner);
            // Output in URL-safe format
            token = jwsObject.serialize();
        } catch (KeyLengthException e) {
            e.printStackTrace();
        } catch (JOSEException e) {
            e.printStackTrace();
        }

        return token;
    }

    /**
     * 校验token是否合法，返回Map集合,集合中主要包含
     * state状态码   data鉴权成功后从token中提取的数据
     * 该方法在过滤器中调用，每次请求API时都校验
     *
     * @param token
     * @return
     */
    public static Map<String, Object> validToken(String token) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 创建jwsObject
            JWSObject jwsObject = JWSObject.parse(token);
            // 创建验证
            JWSVerifier verifier = new MACVerifier(SECRET);
            // 验证token
            if (jwsObject.verify(verifier)) {
                Payload payload = jwsObject.getPayload();
                JSONObject jsonObject = payload.toJSONObject();
                /*// 设置token状态
                result.put(Const.TOKEN_STATE, TokenState.VALID.getState());

                // 校验是否过期
                if (jsonObject.containsKey(Const.EXT)){
                    long extTime = Long.valueOf(jsonObject.get(Const.EXT).toString());
                    long currentTime = System.currentTimeMillis();
                    if (currentTime > extTime) { // 过期的场合
                        result.clear();
                        result.put(Const.TOKEN_STATE, TokenState.EXPIRED.getState());
                    }

                    result.put(Const.USERID, jsonObject.get(Const.USERID));
                    result.put(Const.PASSWORD, jsonObject.get(Const.PASSWORD));
                }*/
            } else {
                // 校验失败--无效
                //result.put(Const.TOKEN_STATE, TokenState.INVALID.toString());
            }
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (KeyLengthException e) {
            e.printStackTrace();
        } catch (JOSEException e) {
            e.printStackTrace();
        }

        return result;
    }


    public static void main(String[] args) throws Exception{
        SecureRandom random = new SecureRandom();
        byte[] sharedSecret = new byte[32];
        random.nextBytes(sharedSecret);
        System.out.println(Arrays.toString(sharedSecret));
        String s = Base64.encodeBase64URLSafeString(sharedSecret);
        System.out.println(s);
        System.out.println(Arrays.toString(Base64.decodeBase64(s)));
    }

}
